;======================================================================= ; ; Name: ICEU10.700 ; ; Group: S-NES Emulator SE BIOS. ; ; Revision: 1.02 ; ; Date: 11/05/2004 ; ; Author: Frank Hughes ; ; ; Changes: ; ; DATE REVISION DESCRIPTION ; -------- -------- ------------------------------------------------------- ; 11/05/4 1.02 Corrected name of the ROM Dumper. ; 30/03/4 1.01 Added name of the ROM Dumper to Source Description. ; 12/11/3 1.00 Original ; ; Description: ; ; This is a Reverse Engineering of the sound code ; used in the Development Unit, 'S-NES Emulator SE'. ; It provides functions to allow the S-NES CPU to play one ; of two samples with various timbre and envelopes, allows ; modification to these presets, and can pass requested ; RAM data back to the S-NES. ; I plan on writing a S-NES interface to allow users ; to experiment with this interesting piece of software! :) ; ; *Big* thanks to interacti for dumping this ROM. ; Note: this code is the property of Nintendo Co. Ltd., and ; is provided here for non-profit and educational purposes. ; ; --- Snes-CPU Commands to the Snes-APU: --- ; 01: Setup Voice Data (SCPUIO0 = Table No.) and play voice. ; $02: Stop Voice. ; $7f: Play voice. ; -ve: S-SDSP Write (SCPUIO0 = Data , SCPUIO1 = Addr (lower 7bits). ; default: Send APU-RAM byte to S-SCPU (SCPUIO2/3 = APU-RAM Addr). ; ; --- APU Block Structure --- ; Block 00: start $0800 length $01F5 ; Block 01: start $8000 length $0008 ; Block 02: start $8100 length $007E ; Execution Address: $0800 ; --------------------------- ; ; --- Memory Map: --- ; $0000 - $007f : S-SDSP Buffer (mirror image of Addresses). ; $0080 - $0081 : Indirect Pointer. ; $0091 - $0091 : Voice Parameter Table number. ; $09ae - $09f4 : A table of 8 Voice parameters (8-bytes a piece). ; $8000 - $8007 : Source Directory. ; $8100 - $817d : Source Data. ; ------------------- ; ;======================================================================= ApuBlockStart $0800 ApuBiosBegin clrp ; Set Direct Page to Page0. mov x,#$cf ; Load X with Stack Top. mov sp,x ; Set Stack Top to #$cf. mov a,#$00 ; Write value to 0. mov x,a ; Indirect Index to 0. ; -- Zero RAM Area $00~$c7. _dis0807 mov (x)+,a cmp x,#$c8 bne _dis0807 ;--- Initialise S-DSP Unused Voices. mov y,#$10 ; Preset to Voice #1. _dis080e push y ; Push Current Voice index onto stack. mov a,#$00 ; VOL_L = 0. call _dis09ee ; Write Byte to S-SDSP. inc y mov a,#$00 ; VOL_R = 0. call _dis09ee ; Write Byte to S-SDSP. inc y inc y inc y mov a,#$00 ; SCRN = $00. call _dis09ee ; Write Byte to S-SDSP. inc y mov a,#$00 ; ADSR_1 = $00. call _dis09ee ; Write Byte to S-SDSP. inc y inc y mov a,#$00 ; GAIN = 0. call _dis09ee ; Write Byte to S-SDSP. pop a ; Pull Current Index off the stack. clrc ; Reset Carry for Addition. adc a,#$10 ; Adjust to next channel index. mov y,a ; Transfer back to Y. cmp a,#$80 ; Done for all channels? bne _dis080e ; Loop back if no. ;--- Voice 0 Initialisation. mov y,#$2c ; EVOL_L mov a,#$00 ; Set Echo Volume (Left) to 0. call _dis09ee ; Write Byte to S-SDSP. mov y,#$3c ; EVOL_R mov a,#$00 ; Set Echo Volume (Right) to 0. call _dis09ee ; Write Byte to S-SDSP. mov y,#$0d ; EFB mov a,#$00 ; Set Echo Feedback to 0. call _dis09ee ; Write Byte to S-SDSP. mov y,#$7d ; EDL mov a,#$00 ; Set Echo Delay to 0. call _dis09ee ; Write Byte to S-SDSP. mov a,#$80 ; Source Directory Address = $8000. mov y,#$5d ; DIR call _dis09ee ; Write Byte to S-SDSP. mov a,#$20 ; Noise Off, Enable Echo Region. mov y,#$6c ; FLG call _dis09ee ; Write Byte to S-SDSP. ; ================= Setup Default parameter for Voice. ================== ; --- Set Main Volume to +96. mov a,#$60 mov $000c,a ; Variable for Main Volume Left. mov $001c,a ; Variable for Main Volume Right. ; --- Disable Echo Memory Area. mov a,#$20 ; #%0-0-1-000000 (Echo Memory Disable) mov $006c,a ; FLG ; --- Disable Pitch Modulation, Noise and Echo. mov a,#$00 mov $002d,a ; Variable for Pitch Modulation. mov $003d,a ; Variable for Noise Flag. mov $004d,a ; Variable for Voice Echo On/Off. ; --- Set Main Volume to +96. mov a,#$60 mov $0000,a ; Variable for Voice0 Volume Left. mov $0001,a ; Variable for Voice0 Volume Right. ; --- Set Pitch Height. mov a,#$08 mov $0002,a mov a,#$08 mov $0003,a ; --- Set Source Offset. mov a,#$01 mov $0004,a ; --- Set ADSR_1 mov a,#$8d mov $0005,a ; --- Set ADSR_2 mov a,#$c4 mov $0006,a ; --- Set Gain Type. mov a,#$7f mov $0007,a ; ============================ S-SCPU Wait. =============================== _dis08a0 mov a,$00f5 ; Fetch SCPUIO1 cmp a,$0092 ; Compare to SnesCpuPrevApuCmd. beq _dis08a0 ; Continue to poll if it was the same. ; --- Here if new ApuCmd. mov $0092,a ; Set as SnesCpuPrevApuCmd. cmp a,#$00 ; Check if ApuCmd#0. beq _dis08a0 ; Branch back if we passed zero. ; --- Here if ApuCmd !=0. mov y,$00f4 ; Y<-SCPUIO0 mov $0091,y ; SnesCpuIOBuffer0 <- SCPUIO0 mov $0090, a ; SnesCpuIOBuffer1 <- SCPUIO1 mov $00f5,a ; SCPUIO1 <- SnesCpuIObuffer1 ;--- Check ApuCmd. cmp a,#$01 ; Check if ApuCmd#1. beq _dis08fe ; Branch if 'yes'. cmp a,#$02 ; Check if ApuCmd#2. beq _dis08f4 ; Branch if 'yes'. cmp a,#$7f ; Check if ApuCmd#127. beq _dis0901 ; Branch if 'yes'. cmp a,#$00 ; Condition Status_Negative flag. bmi _dis08e1 ; Branch if ApuCmd > $7f. ; --- Fall through ApuCmd. mov a,$00f6 ; Fetch low byte of addr from SCPUIO2. mov $0080,a ; Store as low word of pointer. mov a,$00f7 ; Fetch high byte of addr from SCPUIO3. mov $0081,a ; Store as high word of pointer. mov x,#$00 ; Init index for indirection. mov a,[$80+x] ; Fetch RAM value. mov $00f7,a ; Pass Back S-NES via SCPUIO3. jmp _dis08a0 ; Jump back to 'Poll S-SCPU'. ; --- Here if S-SCPU Command -ve. ; Write Byte to S-SDSP Buffer. ; "PAGE0[SnesCpuIOBuffer1 & 0x7f] = SnesCpuIOBuffer0;" _dis08e1 mov a,$0090 ; Fetch SnesCpuIOBuffer1. and a,#$7f ; Mask off Sign bit. mov x,a ; Pass it to X. mov y,a ; Pass it to Y. mov a,$0091 ; Fetch SnesCpuIOBuffer0. mov $0000+x,a ; PAGE0[SnesCpuIOBuffer1 & 0x7f] = SnesCpuIOBuffer0; call _dis09ee ; Write Byte to S-SDSP. jmp _dis08a0 ; Jump back to 'Poll S-SCPU'. ; --- Here if S-SCPU Command #2. _dis08f4 mov y,#$5c ; KOF mov a,#$7f ; voices 0~6 call _dis09ee ; Write Byte to S-SDSP. jmp _dis08a0 ; Jump Back to 'Poll S-SCPU'. ; --- Here if S-SCPU Command #1. _dis08fe call _dis0980 ; Copy table data. ; ================ Refresh S-SDSP with buffer data ===================== ; --- Here if S-SCPU Command #$7f. _dis0901 mov y,#$4c ; KON mov a,#$00 ; clear voices 0~7. call _dis09ee ; Write Byte to S-SDSP. ; --- Clear settings for voices 0~7. mov y,#$5c ; KOF call _dis09ee ; Write Byte to S-SDSP. ; --- Main Volume. mov a,$000c ; Variable for Main Volume (Left). mov y,#$0c ; MVOL(L). call _dis09ee ; Write Byte to S-SDSP. mov a,$001c ; Variable for Main Volume (Right). mov y,#$1c ; MVOL(R). call _dis09ee ; Write Byte to S-SDSP. ; --- Flag Register. mov a,$006c ; Variable for Flag Register. mov y,#$6c ; FLG call _dis09ee ; Write Byte to S-SDSP. ; --- Pitch Modulation. mov a,$002d ; Variable for Pitch Modulation. mov y,#$2d ; PMON. call _dis09ee ; Write Byte to S-SDSP. ; --- Noise On/Off. mov a,$003d ; Variable for Noise On/Off. mov y,#$3d ; EVOL_R call _dis09ee ; Write Byte to S-SDSP. ; --- Echo On/Off. mov a,$004d ; Variable for Echo ON/OFF. mov y,#$4d ; EON call _dis09ee ; Write Byte to S-SDSP. ; --- Voice0 Volume. mov y,#$00 ; VOL_L mov a,$0000 ; Variable for Voice0 Volume Left. call _dis09ee ; Write Byte to S-SDSP. inc y ; VOL_R mov a,$0001 ; Variable for Voice0 Volume Right. call _dis09ee ; Write Byte to S-SDSP. ; --- Voice0 Pitch Height inc y ; P_L mov a,$0002 ; Var for Voice0 Pitch Height (low). call _dis09ee ; Write Byte to S-SDSP. inc y ; P_H mov a,$0003 ; Var for Voice0 Pitch Height (high). call _dis09ee ; Write Byte to S-SDSP. ; --- Voice0 Source Number. inc y ; SCRN mov a,$0004 ; Variable for Voice0 Source Number. call _dis09ee ; Write Byte to S-SDSP. ; --- Voice0 ADSR. inc y ; ADSR_1 mov a,$0005 call _dis09ee ; Write Byte to S-SDSP. inc y ; ADSR_2 mov a,$0006 call _dis09ee ; Write Byte to S-SDSP. ; --- Voice0 Gain Type. inc y ; GAIN mov a,$0007 ; Variable for Gain Envelope Type. call _dis09ee ; Write Byte to S-SDSP. ; --- Voice Enable. mov y,#$4c ; KON mov a,#$01 ; Enable voice #0. call _dis09ee ; Write Byte to S-SDSP. ; --- End of Refresh. jmp _dis08a0 ; Jump back to 'Poll S-SCPU'. ;--------------------------------------- ; Fetch Selected Table of Voice Parameters ; and Pass to our variable table. _dis0980 mov a,$0091 ; Move this value into the accum. and a,#$07 ; Mask to leave 0~7 table access. asl a ; Multiply by 8. asl a asl a mov x,a ; Use as 8-byte table index. ;--- Pitch Height (low) mov a,$09ae+x ; Transfer these values. mov $0002,a ;--- Pitch Height (high) mov a,$09af+x mov $0003,a ;--- Source Number. mov a,$09b0+x mov $0004,a ;--- ADSR_1 mov a,$09b1+x mov $0005,a ;--- ADSR_2 mov a,$09b2+x mov $0006,a ;--- Gain Type. mov a,$09b3+x mov $0007,a ret ; Return ;--------------------------------------- ; Table of Voice Parameters (0~7) ; DB $00,$10,$00,$CD,$CF,$00,$00,$00 DB $00,$0C,$01,$AD,$8F,$00,$00,$00 DB $00,$0E,$00,$88,$E0,$00,$00,$00 DB $00,$10,$01,$88,$E0,$00,$00,$00 DB $00,$20,$00,$CD,$D8,$00,$00,$00 DB $00,$18,$00,$CD,$CF,$00,$00,$00 DB $00,$0A,$01,$CD,$D8,$00,$00,$00 DB $00,$14,$01,$CD,$CF,$00,$00,$00 ; ====== Write a byte to the S-SDSP ========= _dis09ee mov $00f2,y mov $00f3,a ret ApuBlockend ; =========================================== ApuBlockStart $8000 ; --- Source Directory. DW Src0Start ; Source#0 Start Address. DW Src0Loop ; Source#0 Loop Address. DW Src1Start ; Source#1 Start Address. DW Src1Loop ; Source#1 Loop Address. ApuBlockEnd ;------------------------------------------------------------------ ApuBlockStart $8100 ; Source#0 ; Address $8100 Src0Start DB %00000010 ; Range=0,Filter=no,Loop=yes,End=no. DB $00,$00,$00,$00,$00,$00,$00,$00 DB %10010110 ; Range=9,Filter=1st,Loop=yes,End=no. DB $00,$00,$00,$07,$55,$54,$43,$43 DB %10011110 ; Range=9,Filter=3rd,Loop=yes,End=no. DB $00,$10,$00,$00,$F0,$F0,$FE,$ED ; Source#0 Loop Address. Src0Loop DB %01111110 ; Range=7,Filter=3rd,Loop=yes,End=no. DB $22,$0E,$DF,$E0,$0F,$E0,$F0,$12 DB %10001110 ; Range=8,Filter=3rd,Loop=yes,End=no. DB $10,$12,$22,$42,$20,$02,$01,$11 DB %10011110 ; Range=9,Filter=3rd,Loop=yes,End=no. DB $00,$01,$0F,$10,$FF,$00,$E0,$CE DB %01111111 ; Range=7,Filter=3rd,Loop=yes,End=yes. DB $12,$0E,$DF,$E0,$0F,$E0,$0F,$12 ;-------------------------------------------------------------------- ; Source#1 ; Address $813f Src1Start DB %00000010 ; Range=0,Filter=no,Loop=yes,End=no. DB $00,$00,$00,$00,$00,$00,$00,$00 DB %10011110 ; Range=9,Filter=3rd,Loop=yes,End=no. DB $00,$00,$00,$0E,$D3,$20,$F0,$E1 DB %10101110 ; Range=10,Filter=3rd,Loop=yes,End=no. DB $EE,$02,$45,$0E,$E0,$F0,$F1,$01 # Source#1 Loop Address Src1Loop DB %10111110 ; Range=11,Filter=3rd,Loop=yes,End=no. DB $10,$01,$ED,$E1,$21,$10,$F1,$F0 DB %10010110 ; Range=9,Filter=1st,Loop=yes,End=no. DB $ED,$E3,$66,$FA,$CE,$12,$0F,$FF DB %10101110 ; Range=10,Filter=3rd,Loop=yes,End=no. DB $EE,$03,$35,$0E,$E0,$0F,$F1,$02 DB %10111111 ; Range=11,Filter=3rd,Loop=yes,End=yes. DB $01,$00,$EE,$E0,$22,$01,$F0,$0F ApuBlockEnd ; --------------------------------------- ApuBlockExec ApuBiosBegin